package org.lc.platform.mybatis.manager.relation;

import cn.hutool.core.util.StrUtil;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import static cn.hutool.core.collection.CollUtil.emptyIfNull;

public class RelationBuilder<T> extends BaseRelation<T> {


    public RelationBuilder(Relation relation, List<T> data) {
        this(relation, data, List.of());
    }

    public RelationBuilder(Relation relation, List<T> data, List<Map<String, Object>> relationList) {
        this.relationList = relationList;
        this.relation = relation;
        this.data = data;
    }

    public static <K> RelationBuilder<K> of(Relation relation, List<K> data) {
        return new RelationBuilder<>(relation, data);
    }

    public static <K> RelationBuilder<K> of(Relation relation, List<K> data, List<Map<String, Object>> relationList) {
        return new RelationBuilder<>(relation, data, relationList);
    }

    /**
     * 当前实体类关联的字段名称
     */
    private String getSRN() {
        return this.relation.getSelfRelationName();
    }

    /**
     * 当前实体类关联的字段数据库名称
     */
    private String getSRTN() {
        return this.relation.getSelfRelationTableName();
    }

    /**
     * 当前表被注解的字段名称
     */
    private String getSN() {
        return this.relation.getSelfName();
    }

    /**
     * 关联中间表对应目标实体的字段名
     */
    private String getTMRN() {
        return this.relation.getTargetMiddleName();
    }

    /**
     * 关联中间表对应目标实体的字段数据库名
     */
    private String getTMRTN() {
        return this.relation.getTargetMiddleTableName();
    }

    /**
     * 关联中间表对应当前实体的字段名
     */
    private String getSMRN() {
        return this.relation.getSelfMiddleName();
    }

    /**
     * 关联中间表对应当前实体的数据库字段名
     */
    private String getSMRTN() {
        return this.relation.getSelfMiddleTableName();
    }

    /**
     * 关联目标实体类的字段名称
     */
    private String getTRN() {
        return this.relation.getTargetRelationName();
    }

    /**
     * 关联目标实体类的字段数据库名称
     */
    private String getTRTN() {
        return this.relation.getTargetRelationTableName();
    }

    /**
     * 关联中间表实体类Class对象
     */
    private Class<?> getRMC() {
        return this.relation.getRelationMiddleCls();
    }

    /**
     * 关联目标实体类Class对象
     */
    private Class<?> getRC() {
        return this.relation.getRelationCls();
    }


    /**
     * 处理记录
     * （多对一，一对一）
     */
    public void processToOne() {
        processMultiple(false);
    }

    /**
     * 处理记录
     * （一对多）
     */
    public void processToMany() {
        processMultiple(true);
    }

    /**
     * 处理记录
     * （多对多）
     */
    public void processManyToMany() {
        processManyToManyMultiple();
    }

    private void processMultiple(boolean multiple) {
        var values = getSetList(data, getSRN());
        var result = getQueryResult(getRC(), getTRTN(), values);
        if (result != null && !result.isEmpty()) {
            var map = getGroupByData(result, getTRN());
            if (!map.isEmpty()) {
                data.forEach(r -> {
                    Object key = getReflectValue(r, getSRN());
                    if (!StrUtil.isEmptyIfStr(key) && Optional.ofNullable(map.get(key)).isPresent()) {
                        setReflectValue(r, getSN(), multiple ? map.get(key) : map.get(key).getFirst());
                    }
                });
            }
        }
    }

    private void processManyToManyMultiple() {
        var values = getSetList(data, getSRN());
        var middleResult = getQueryResult(getRMC(), getSMRTN(), values);
        var middleIds = getSetList(middleResult, getTMRN());
        var middleMap = getGroupByData(middleResult, getSMRN(), getTMRN());
        if (!middleIds.isEmpty()) {
            var result = getQueryResult(getRC(), getTRTN(), middleIds);
            data.forEach(d -> {
                var targetResult = result.stream().filter(e -> emptyIfNull(middleMap.get(getReflectValue(d, getSRN()))).contains(getReflectValue(e, getTRN()))).toList();
                setReflectValue(d, getSN(), targetResult);
            });
        }
    }
}
